<?php

namespace joncc\fs;

class FileSize
{
    const B = 'B';
    const KB = 'KB';
    const MB = 'MB';
    const GB = 'GB';
    private static $dir = [];
    private static $files = [];
    private static $size = 5 * 1024 * 1024;
    private static $unit = self::MB;

    public static function setUnitB()
    {
        self::$unit = self::B;
    }

    public static function setUnitKB()
    {
        self::$unit = self::KB;
    }

    public static function setUnitMB()
    {
        self::$unit = self::MB;
    }

    public static function setUnitGB()
    {
        self::$unit = self::GB;
    }

    public static function getSize()
    {
        return self::$size;
    }

    public static function setSize($size)
    {
        self::$size = $size * self::getUnitRate();
    }

    public static function getDir()
    {
        return self::$dir;
    }

    /**
     * @param string $dir
     */
    public static function addDir($dir)
    {
        self::$dir[] = $dir;
    }

    public static function clearDir()
    {
        self::$dir = [];
        self::$files = [];
    }

    public static function sizeStat()
    {
        self::getFiles();

        $u = self::$unit;
        echo str_repeat('=', 120) . PHP_EOL;
        echo str_repeat("\t", 6) . " 文件大小列表/{$u}" . PHP_EOL;
        echo str_repeat('=', 120) . PHP_EOL;

        $stat_total_files = 0;
        $stat_total_size = 0;
        $stat_big_file_list = [];
        foreach (self::$files as $dir => $files) {

            $total_file = 0;
            $total_size = 0;
            foreach ($files as $file) {
                $f = $dir . DIRECTORY_SEPARATOR . $file;
                $s = filesize($f);

                if ($s >= self::getSize()) {
                    echo "|-- $file " . self::fontColor(self::getUnit($s), 'warning') . PHP_EOL;
                    $stat_big_file_list[$f] = $s;
                }

                $total_file++;
                $total_size += $s;

                $stat_total_files++;
                $stat_total_size += $s;
            }


            echo '|---- ' . $dir . "\ttotal files: $total_file\ttotal size: " . self::getUnit($total_size) . PHP_EOL;
            echo str_repeat('-', 120) . PHP_EOL;
        }

        self::stat($stat_total_files, $stat_total_size, $stat_big_file_list);
    }

    public static function sizeAllStat()
    {
        self::getFiles();

        $u = self::$unit;
        echo str_repeat('=', 120) . PHP_EOL;
        echo str_repeat("\t", 6) . " 文件大小列表/{$u}" . PHP_EOL;
        echo str_repeat('=', 120) . PHP_EOL;

        $stat_total_files = 0;
        $stat_total_size = 0;
        $stat_big_file_list = [];
        foreach (self::$files as $dir => $files) {

            $total_file = 0;
            $total_size = 0;
            echo '|' . PHP_EOL;
            foreach ($files as $file) {
                $f = $dir . DIRECTORY_SEPARATOR . $file;
                $s = filesize($f);

                echo "|-- $file ";
                if ($s >= self::getSize()) {
                    echo self::fontColor(self::getUnit($s), 'warning');
                    $stat_big_file_list[$f] = $s;
                } else {
                    echo self::getUnit($s);
                }

                echo PHP_EOL;

                $total_file++;
                $total_size += $s;

                $stat_total_files++;
                $stat_total_size += $s;
            }

            echo '|---- ' . $dir . "\ttotal files: $total_file\ttotal size: " . self::getUnit($total_size) . PHP_EOL;
            echo str_repeat('-', 120) . PHP_EOL;
        }

        self::stat($stat_total_files, $stat_total_size, $stat_big_file_list);
    }

    private static function stat($stat_total_files, $stat_total_size, $stat_big_file_list)
    {
        echo PHP_EOL . PHP_EOL . str_repeat('-', 70) . PHP_EOL;
        if (!empty($stat_big_file_list)) {
            echo self::fontColor('| big file list (size>=' . self::getUnit(self::getSize()) . '):') . PHP_EOL;
            foreach ($stat_big_file_list as $f => $size) {
                echo '| ' . $f . ' ' . self::getUnit($size) . PHP_EOL;
            }
            echo '|' . PHP_EOL;
        }

        echo self::fontColor('| file stat:') . PHP_EOL . '| total files: ' . $stat_total_files . PHP_EOL;
        echo '| total size: ' . self::getUnit($stat_total_size) . PHP_EOL;
        if (!empty($stat_big_file_list)) {
            echo self::fontColor('| big file percent: ' . sprintf('%.2f', array_sum($stat_big_file_list) / $stat_total_size * 100) . '%') . PHP_EOL;
        }
        echo str_repeat('-', 70) . PHP_EOL . PHP_EOL;
    }

    private static function fontColor($text, $color = 'info')
    {
        $styles = array(
            'success' => "\033[0;32m%s\033[0m",
            'error' => "\033[31;31m%s\033[0m",
            'warning' => "\033[0;35m%s\033[0m",
            'info' => "\033[33;33m%s\033[0m",
        );

        return str_replace('%s', $text, isset($styles[$color]) ? $styles[$color] : $styles['info']);
    }

    public static function api()
    {
        self::getFiles();

        return self::$files;
    }

    public static function fileEmpty()
    {
        self::getFiles();

        foreach (self::$files as $dir => $files) {
            foreach ($files as $file) {
                $f = $dir . DIRECTORY_SEPARATOR . $file;
                $s = filesize($f);
                if ($s >= self::getSize()) {
                    file_put_contents($f, '');
                    echo self::fontColor($f . "\t| " . self::getUnit($s) . ' --> 0') . PHP_EOL;
                }
            }
        }
    }

    public static function fileUnlink()
    {
        self::getFiles();

        foreach (self::$files as $dir => $files) {
            foreach ($files as $file) {
                $f = $dir . DIRECTORY_SEPARATOR . $file;
                $s = filesize($f);
                if ($s >= self::getSize()) {
                    unlink($f);
                    echo self::fontColor("remove $f", 'error') . PHP_EOL;
                }
            }
        }
    }

    private static function getUnit($s)
    {
        return round($s / self::getUnitRate()) . self::$unit;
    }

    private static function getUnitRate()
    {
        switch (self::$unit) {
            case self::KB:
                return 1024;
            case self::MB:
                return 1024 * 1024;
            case self::GB:
                return 1024 * 1024 * 1024;
            default:
                return 1;
        }
    }

    private static function getFiles()
    {
        if (!empty(self::$files)) {
            return self::$files;
        }

        foreach (self::getDir() as $dir) {
            self::setFiles($dir);
        }
    }

    private static function setFiles($dir)
    {
        if (is_file($dir)) {
            self::$files[] = $dir;
            return;
        }

        if (!is_dir($dir)) {
            return;
        }

        $files = scandir($dir);
        foreach ($files as $file) {
            if ('.' == substr($file, 0, 1)) {
                continue;
            }

            if (DIRECTORY_SEPARATOR == substr($dir, -1)) {
                $f = $dir . $file;
            } else {
                $f = $dir . DIRECTORY_SEPARATOR . $file;
            }

            if (is_file($f)) {
                if (!isset(self::$files[$dir])) {
                    self::$files[$dir] = [];
                }

                self::$files[$dir][] = $file;
                continue;
            }

            self::setFiles($f);
        }
    }
}